package com.github.aloxc.plugin.restplus.listener;

import com.github.aloxc.plugin.restplus.common.Consts;
import com.github.aloxc.plugin.restplus.common.UploadYapi;
import com.github.aloxc.plugin.restplus.component.ServiceNode;
import com.github.aloxc.plugin.restplus.entity.*;
import com.github.aloxc.plugin.restplus.i18n.I18Bundle;
import com.github.aloxc.plugin.restplus.navigation.action.RestServiceItem;
import com.github.aloxc.plugin.restplus.navigator.RestServiceDetail;
import com.github.aloxc.plugin.restplus.popup.PopupBalloon;
import com.github.aloxc.plugin.restplus.resolver.*;
import com.github.aloxc.plugin.restplus.utils.JavaScriptUtil;
import com.github.aloxc.plugin.restplus.utils.Log;
import com.github.aloxc.plugin.restplus.utils.StringUtils;
import com.github.aloxc.plugin.restplus.utils.ToolkitUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiMethod;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

/**
 * tree列表推送接口到yapi
 */
public class PushYapiActionListener implements ActionListener {
    private JComponent component;
    private RestServiceDetail restServiceDetail;

    public PushYapiActionListener(RestServiceDetail restServiceDetail) {
        this.restServiceDetail = restServiceDetail;
    }

    public void setComponent(JComponent component) {
        this.component = component;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (StringUtils.isNullOrEmpty(restServiceDetail.getUrl())) {
            return;
        }

        Module module = restServiceDetail.getModule();
        if(module == null){
            //这是从swagger导入的，不支持推送到yapi
            PopupBalloon.showPopupBalloon(component,I18Bundle.getMessage("com.github.aloxc.plugin.restplus.yapi.swagger.text"), false);
            return;
        }
        RestConfig config = RestConfig.loadConfig(restServiceDetail.getProject());
        if(config == null){
            PopupBalloon.showPopupBalloon(component,I18Bundle.getMessage("com.github.aloxc.plugin.restplus.yapi.noconfig.text"), false);
            return;
        }
        Yapi yapi = config.getYapi(module);
        if(yapi == null || StringUtils.isNullOrEmpty(yapi.getToken()) || StringUtils.isNullOrEmpty(yapi.getProjectId()) || StringUtils.isNullOrEmpty(yapi.getUrl())){
            PopupBalloon.showPopupBalloon(component,I18Bundle.getMessage("com.github.aloxc.plugin.restplus.yapi.noconfig.text"), false);
            return;
        }

        JTree tree= (JTree)component;
        DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();

        if(! (selNode instanceof ServiceNode)){
            return;
        }

        ServiceNode serviceNode = (ServiceNode) selNode;
        final RestServiceItem restServiceItem = serviceNode.getRestServiceItem();
        List<RestServiceItem> itemList = new ArrayList<>();
        SpringResolver springResolver = new SpringResolver(module);
        JaxrsResolver jaxrsResolver = new JaxrsResolver(module);
        MicronautResolver micronautResolver = new MicronautResolver(module);
        ServiceResolver[] resolvers = {springResolver,jaxrsResolver,micronautResolver};
        for (ServiceResolver resolver : resolvers) {
            List<RestServiceItem> allSupportedServiceItemsInModule = resolver.findAllSupportedServiceItemsInModule();
            itemList.addAll(allSupportedServiceItemsInModule);
        }
        if(itemList.size() == 0){
            return;
        }

        RestServiceItem curItem = itemList.stream().filter(item -> {
            if (
                    item.getPsiMethod().getName().equals(restServiceItem.getPsiMethod().getName())
                            && item.getPsiClass().getName().equals(restServiceItem.getPsiClass().getName())
                            && item.getModule().getName().equals(restServiceItem.getModule().getName())
                            && item.getUrl().equals(restServiceItem.getUrl())
                            && item.getMethod().name().equals(restServiceItem.getMethod().name())
                            && item.isFoundRequestBody() == restServiceItem.isFoundRequestBody()
            ) {
                return true;
            }
            return false;
        }).findFirst().orElse(null);


        IYapiResolver yapiResolver = getYapiResolver(curItem.getModule().getProject(), curItem.getPsiMethod());
        YapiDTO yapiDTO = yapiResolver.buildYapi(serviceNode);
        final YApiSaveParam yapiSaveParam = new YApiSaveParam(yapi.getToken(), yapiDTO.getTitle(), yapiDTO.getPath(), yapiDTO.getParams(), yapiDTO.getRequestBody(),
                yapiDTO.getResponse(), Integer.valueOf(yapi.getProjectId()), yapi.getUrl(), true, yapiDTO.getMethod(), yapiDTO.getDesc(), yapiDTO.getHeader());
        yapiSaveParam.setReq_body_form(yapiDTO.getReq_body_form());
        yapiSaveParam.setReq_body_type(yapiDTO.getReq_body_type());
        yapiSaveParam.setReq_params(yapiDTO.getReq_params());
        yapiSaveParam.setMenu(yapiDTO.getMenu());
        ToolkitUtil.invokeLater(curItem.getModule().getProject(), new Runnable() {
            @Override
            public void run() {
                try {
                    YapiResponse yapiResponse = new UploadYapi().uploadSave(yapiSaveParam, false);
                    if (yapiResponse.getErrcode() != 0) {
                        PopupBalloon.showPopupBalloon(component, "sorry ,upload api " + yapiDTO.getPath() + " error cause:" + yapiResponse.getErrmsg(), true);
                    } else {
                        StringBuffer html = new StringBuffer();
                        String desc = yapiSaveParam.getTitle();
                        html.append("URL<br/><a href=\"").append(yapiResponse.getData()).append("\">").append(yapiResponse.getData()).append("</a>");
                        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                        String path = "[" + desc + "]\r\n" + yapiResponse.getData();
                        clipboard.setContents(new StringSelection(path), null);
                        PopupBalloon.showPopupBalloon(component, "success , you can see["+desc+"] :  " + html.toString(), false);
                    }
                }catch (Exception e1){
                    Writer result = new StringWriter();
                    PrintWriter printWriter = new PrintWriter(result);
                    e1.printStackTrace(printWriter);
                    String msg = result.toString();
                    msg.replaceAll("\\\\r\\\\n","<br>");
                    Log.log1("提交yapi异常" + JavaScriptUtil.class.getName() +"-" ,msg);
                    PopupBalloon.showPopupBalloon(component,"exception ,url" + yapiDTO.getPath(),true);
                }
            }
        });
    }


    /**
     * 通过策略获取yapi业务处理类
     * @param project
     * @param psiMethod
     * @return
     */
    public IYapiResolver getYapiResolver(Project project,PsiMethod psiMethod){
        Consts.ServiceType serviceType = Consts.ServiceType.getServiceType(psiMethod);
        if (serviceType == Consts.ServiceType.JAXRS) {
            return new JaxrsResolver(project);
        } else if(serviceType == Consts.ServiceType.MICRONAUT) {
            return new MicronautResolver(project);
        }else{
            return new SpringResolver(project);
        }
    }
}